import streamlit as st
import matplotlib.pyplot as plt  
from datetime import datetime
import pandas as pd
import numpy as np
from snownlp import SnowNLP

def analyze_comment_sentiment(text):
    """分析单条评论的情绪值（0-1，越接近1越积极）"""
    try:
        s = SnowNLP(text)
        return s.sentiments  
    except:
        return 0.5  # 中性情绪作为默认值

def batch_analyze_sentiments(comments_df):
    """批量分析评论情绪（带错误处理）"""
    if comments_df is None or comments_df.empty:
        return pd.DataFrame()
    
    # 检查是否有 text 列
    if 'text' not in comments_df.columns:
        st.error("错误：DataFrame 中没有 'text' 列")
        st.write("可用的列:", list(comments_df.columns))
        return pd.DataFrame()
    
    sentiments = []
    progress_bar = st.progress(0)
    total_comments = len(comments_df)
    
    for idx, text in enumerate(comments_df['text']):
        sentiment = analyze_comment_sentiment(text)
        sentiments.append(sentiment)
        if idx % 100 == 0:  # 每100条更新一次进度
            progress_bar.progress((idx + 1) / total_comments)
    
    comments_df = comments_df.copy()
    comments_df['sentiment'] = sentiments
    progress_bar.empty()
    
    return comments_df

def analyze_temporal_trends(comments_df):
    """分析情绪时间序列"""
    if comments_df is None or comments_df.empty:
        return pd.Series(dtype=float)
    
    comments_df['time'] = pd.to_datetime(comments_df['time'])
    comments_df = comments_df.sort_values('time')
    
    # 按小时聚合情绪均值
    hourly_sentiment = comments_df.set_index('time').resample('H')['sentiment'].mean()
    
    return hourly_sentiment

def detect_events(sentiment_series, threshold=2.0):
    """检测情绪异常事件"""
    if sentiment_series is None or len(sentiment_series) == 0:
        return pd.Series(dtype=float)
    
    mean = sentiment_series.mean()
    std = sentiment_series.std()
    
    if std == 0:  # 避免除零错误
        return pd.Series(dtype=float)
    
    events = sentiment_series[abs(sentiment_series - mean) > threshold * std]
    return events

def calculate_entropy(sentiment_values):
    """计算情绪熵值 - 衡量文化圈子的混乱程度"""
    if sentiment_values is None or len(sentiment_values) == 0:
        return 0.0
    
    try:
        # 将情绪值分箱离散化
        hist, bin_edges = np.histogram(sentiment_values, bins=10, range=(0, 1), density=True)
        prob = hist / hist.sum()
        
        # 计算香农熵（避免log(0)）
        entropy = -np.sum([p * np.log2(p + 1e-10) for p in prob if p > 0])
        return float(entropy)
    except Exception as e:
        st.warning(f"熵计算错误: {e}")
        return 0.0

def calculate_entropy_over_time(temporal_data, window_size=6):
    """计算时间序列上的滑动窗口熵值 - 文化波动指标"""
    if temporal_data is None or len(temporal_data) < window_size:
        return pd.Series(dtype=float)
    
    entropy_values = []
    indices = []
    
    for i in range(len(temporal_data) - window_size + 1):
        window = temporal_data.iloc[i:i+window_size]
        entropy_val = calculate_entropy(window)
        entropy_values.append(entropy_val)
        indices.append(temporal_data.index[i + window_size - 1])
    
    return pd.Series(entropy_values, index=indices)

def calculate_thermodynamic_entropy(sentiment_series, temperature=1.0):
    """
    基于热力学概念的熵计算 - 文化热力学模型
    temperature: 文化活跃度参数，值越大系统越活跃
    """
    if len(sentiment_series) == 0:
        return 0
    
    # 玻尔兹曼熵公式启发
    energy_levels = np.array(sentiment_series)
    temperature = max(temperature, 0.1)  # 避免除以零
    
    probabilities = np.exp(-energy_levels / temperature) 
    probabilities = probabilities / np.sum(probabilities)
    
    # 计算熵值（添加小常数避免log(0)）
    entropy = -np.sum(probabilities * np.log(probabilities + 1e-10))
    return entropy

def identify_cultural_phase(entropy_series, stability_threshold=0.1):
    """
    识别文化圈子的不同演化相位
    返回：相位类型和置信度
    """
    if entropy_series is None or len(entropy_series) < 10:
        return "数据不足", 0.0, None
    
    recent_entropy = entropy_series[-10:]  # 最近10个时间点
    entropy_std = np.std(recent_entropy)
    entropy_mean = np.mean(recent_entropy)
    
    # 计算趋势
    if len(recent_entropy) > 1:
        entropy_trend = np.polyfit(range(len(recent_entropy)), recent_entropy, 1)[0]
    else:
        entropy_trend = 0
    
    # 相位识别逻辑
    if entropy_std < stability_threshold:
        phase = "文化稳定期" if entropy_mean < 1.0 else "文化混沌期"
        confidence = 1.0 - (entropy_std / stability_threshold)
    elif abs(entropy_trend) > 0.05:
        phase = "文化相变期" 
        confidence = min(abs(entropy_trend) * 2, 1.0)
    else:
        phase = "文化过渡期"
        confidence = 0.5
    
    return phase, confidence, entropy_trend

def analyze_emotional_network(comments_df, time_window=60):
    """
    分析情绪传播的网络特性 - 文化传播动力学
    """
    if comments_df is None or comments_df.empty:
        return pd.DataFrame()
    
    comments_df = comments_df.sort_values('time')
    comments_df['time_group'] = (comments_df['time'].astype(int) // (time_window * 60)).astype(int)
    
    network_features = []
    for time_group, group in comments_df.groupby('time_group'):
        if len(group) > 10:  # 确保有足够数据
            # 计算网络特征
            emotional_sync = group['sentiment'].std()  # 情绪同步性
            emotional_cascade = group['sentiment'].diff().abs().mean()  # 情绪传播强度
            
            network_features.append({
                'time_window': time_group,
                'emotional_synchronization': emotional_sync,
                'emotional_cascade_strength': emotional_cascade,
                'comment_density': len(group) / time_window,
                'average_sentiment': group['sentiment'].mean()
            })
    
    return pd.DataFrame(network_features)

def simulate_emotional_diffusion(initial_state=0.5, diffusion_rate=0.1, steps=50):
    """
    模拟情绪在网络中的扩散过程 - 文化波动传播模型
    基于热传导方程 ∂u/∂t = α∇²u
    """
    grid_size = (20, 20)
    emotion_grid = np.full(grid_size, initial_state)
    
    # 随机添加情绪源（文化热点）
    sources = [(np.random.randint(5, 15), np.random.randint(5, 15)) for _ in range(3)]
    for x, y in sources:
        emotion_grid[x, y] = np.random.uniform(0.7, 1.0)  # 积极情绪源
    
    # 模拟扩散过程
    history = [emotion_grid.copy()]
    for step in range(steps):
        new_grid = emotion_grid.copy()
        for i in range(1, grid_size[0]-1):
            for j in range(1, grid_size[1]-1):
                # 拉普拉斯算子近似扩散
                laplacian = (emotion_grid[i+1, j] + emotion_grid[i-1, j] +
                           emotion_grid[i, j+1] + emotion_grid[i, j-1] -
                           4 * emotion_grid[i, j])
                new_grid[i, j] += diffusion_rate * laplacian
        
        emotion_grid = np.clip(new_grid, 0, 1)
        history.append(emotion_grid.copy())
    
    return history

def plot_emotional_diffusion(diffusion_history):
    """可视化情绪扩散过程 - 文化波动传播可视化"""
    if not diffusion_history:
        return None
    
    fig, axes = plt.subplots(2, 5, figsize=(15, 6))
    axes = axes.flatten()
    
    # 选择10个时间点显示
    step_indices = np.linspace(0, len(diffusion_history)-1, 10, dtype=int)
    
    for i, step_idx in enumerate(step_indices):
        im = axes[i].imshow(diffusion_history[step_idx], cmap='RdYlBu', vmin=0, vmax=1)
        axes[i].set_title(f'Step {step_idx}')
        axes[i].axis('off')
        plt.colorbar(im, ax=axes[i], shrink=0.6)
    
    plt.suptitle('文化情绪扩散模拟 (热力学传播模型)', fontsize=16)
    plt.tight_layout()
    return fig

def calculate_cultural_volatility_index(entropy_series, sentiment_series):
    """
    计算文化波动指数 - 综合熵值和情绪变化的指标
    """
    if len(entropy_series) < 2 or len(sentiment_series) < 2:
        return 0.0
    
    # 熵值变化率
    entropy_change = np.std(np.diff(entropy_series[-10:])) if len(entropy_series) >= 10 else 0
    
    # 情绪波动率
    sentiment_volatility = np.std(sentiment_series[-10:]) if len(sentiment_series) >= 10 else 0
    
    # 综合波动指数
    volatility_index = entropy_change * 0.6 + sentiment_volatility * 0.4
    
    return volatility_index

def generate_cultural_report(comments_df, temporal_trends, entropy_series):
    """
    生成文化波动分析报告
    """
    if comments_df is None or comments_df.empty:
        return "数据不足，无法生成报告"
    
    report = {
        'total_comments': len(comments_df),
        'time_period': f"{comments_df['time'].min()} 至 {comments_df['time'].max()}",
        'avg_sentiment': comments_df['sentiment'].mean(),
        'sentiment_std': comments_df['sentiment'].std(),
        'max_entropy': entropy_series.max() if not entropy_series.empty else 0,
        'min_entropy': entropy_series.min() if not entropy_series.empty else 0,
        'cultural_phase': identify_cultural_phase(entropy_series)[0] if not entropy_series.empty else "未知"
    }
    
    return report

def emotional_energy_diffusion(emotion_matrix, diffusion_coefficient=0.1):
    """
    模拟情绪能量在网络中的扩散过程（类似热传导）
    """
    # 使用拉普拉斯算子模拟扩散
    laplacian = np.roll(emotion_matrix, 1) + np.roll(emotion_matrix, -1) + \
                np.roll(emotion_matrix, 1, axis=0) + np.roll(emotion_matrix, -1, axis=0) - \
                4 * emotion_matrix
    new_emotion = emotion_matrix + diffusion_coefficient * laplacian
    return np.clip(new_emotion, 0, 1)

def real_time_phase_monitoring(entropy_stream, window_size=10):
    """
    实时文化相位监控
    适用于流数据场景
    """
    phase_history = []
    entropy_buffer = []
    
    for new_entropy in entropy_stream:
        entropy_buffer.append(new_entropy)
        if len(entropy_buffer) > window_size:
            entropy_buffer.pop(0)
        
        if len(entropy_buffer) == window_size:
            current_phase, confidence, _ = identify_cultural_phase(
                pd.Series(entropy_buffer)
            )
            phase_history.append({
                'timestamp': datetime.now(),
                'phase': current_phase,
                'confidence': confidence,
                'entropy': new_entropy
            })
    
    return phase_history

# 为保持兼容性，保留原始函数名
def analyze_emotion_trends(data):
    """分析情绪趋势（兼容性函数）"""
    return analyze_temporal_trends(data)